home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright 2007-2008 Foxmarks Inc.
-
- foxmarks-server.js: component that implements the logical interface to
- the server.
-
- */
-
- // TO DO:
- // * Deal with failure to retrieve baseline state from server -> merge
-
-
-
- function getDatasourceAttribute(synctype, attr){
- switch(synctype){
- case 'bookmarks':
- switch(attr){
- case 'engine':
- return BookmarkDatasource.STORAGE_ENGINE;
- default:
- throw("getDatasourceAttribute: unknown attribute (" + attr + ")");
- }
- break;
- case 'lastmodifieddate':
- break;
- default:
- throw("getDatasourceAttribute: unknown synctype (" + synctype + ")");
- }
-
- }
-
- function hasPasswordSync(){
- return "@mozilla.org/login-manager;1" in Cc;
-
- }
-
- var SYNCSET = {};
- if(hasPasswordSync()){
- SYNCSET = {
- "bookmarks": BookmarkDatasource,
- "passwords": PasswordDatasource
- };
- }
- else {
-
- SYNCSET = {
- "bookmarks": BookmarkDatasource
- };
- }
-
- function createDatasource(type){
- var model = new SYNCSET[type];
- if(model === undefined)
- throw("createDatasource: unknown synctype (" + type +")");
-
- return model;
- }
-
- function loadDatasourceSet(allItems) {
- var result = [];
- var type;
- var obj = {};
- for(type in SYNCSET){
- if(obj[type] === undefined){
- if(Xmarks.gSettings.isSyncEnabled(type) || allItems){
- var model = createDatasource(type);
- result.push(model);
- }
- }
- }
-
-
- return result;
- }
-
- function SyncServer() {
- }
-
- SyncServer.prototype = {
- _syncEngine: null,
- _request: null,
- _baselineCache: {},
- cancel: function() {
- if(this._syncEngine) {
- this._syncEngine.cancel();
- }
- if (this._request){
- this._request.Cancel();
- }
- },
- datacancel: function(){
- if (this._request){
- this._request.Cancel();
- }
- },
- _createSyncEngine: function(datasource){
- var cls = Xmarks.gSettings.useOwnServer ?
- OwnSyncEngine :
- Syncd2SyncEngine;
- var result = new cls(this,datasource);
-
- result.manual = this.manual;
- return result;
- },
-
- getBaseline: function(syncType,callback){
- var ds = createDatasource(syncType);
- var se = this._createSyncEngine(ds);
- se._fetchBaseline(function(status){
- if(se._responseOK(status, callback)){
- callback(0, se._baseline);
- }
- });
- },
- suspendWatcher: function(state){
- var os = Cc["@mozilla.org/observer-service;1"]
- .getService(Ci.nsIObserverService);
- os.notifyObservers(null, "foxmarks-watchersuspend",
- state ? "1" : "0");
- },
-
-
- _doPerDatasource: function(funcname, callback, arg2){
- var list = loadDatasourceSet();
- var that = this;
- var ds = {};
-
- try {
- that.suspendWatcher(true);
-
- // loop through each set of syncdata, using the
- // chained callback mechanism, dropping out if
- // we encounter an error
- var mycallback = function(statuscode){
- if(statuscode == 0 || statuscode == 444){
- // 444 -handle purged state
- if(statuscode == 444){
- // if we allow purge from other data types
- // we'll need to modify this string
- Xmarks.Alert(Xmarks.Bundle().GetStringFromName(
- "msg.passwordsyncpurged"));
- Xmarks.gSettings.setSyncEnabled(ds.syncType, false);
- statuscode = 0;
- }
- if(ds && ds.syncType !== undefined){
- Xmarks.gSettings.SyncComplete(ds.syncType);
- Xmarks.SetProgressComponentStatus(ds.syncType, "end");
- }
- ds = list.shift();
- if(ds){
- that._syncEngine = that._createSyncEngine(ds);
- Xmarks.SetProgressComponentStatus(ds.syncType, "start");
- if(arg2 !== undefined){
- that._syncEngine[funcname](arg2, mycallback);
- }
- else {
- that._syncEngine[funcname](mycallback);
- }
- }
- else {
- callback(statuscode);
- that.suspendWatcher(false);
- that._syncEngine = null;
- if(!Xmarks.gSettings.useBaselineCache){
- that._baselineCache = {};
- }
- }
- }
- else {
- callback(statuscode);
- that.suspendWatcher(false);
- that._syncEngine = null;
- if(!Xmarks.gSettings.useBaselineCache){
- that._baselineCache = {};
- }
- }
- }
-
- mycallback(0);
- }catch(e){
- that.suspendWatcher(false);
- if(typeof e == "object" && e.message){
- Xmarks.LogWrite("Sync Error: " + e.message + "(" +
- e.fileName + ": " + e.lineNumber + ")");
- } else {
- Xmarks.LogWrite("Synchronization failed. Error is " +
- e.toSource() + " (type = " + typeof e + ")");
- }
- if(typeof e == "number"){
- mycallback(e);
- } else {
- mycallback(4);
- }
- }
- },
- sync: function(prevState, callback){
- Xmarks.SetProgressMessage("progress.syncing");
- this._doPerDatasource("sync", callback, prevState);
- },
- upload: function(callback){
- Xmarks.SetProgressMessage("progress.syncing");
- this._doPerDatasource("upload", callback);
- },
- download: function(callback){
- Xmarks.SetProgressMessage("progress.syncing");
- this._doPerDatasource("download", callback);
- },
- merge: function(local, callback){
- Xmarks.SetProgressMessage("progress.syncing");
- this._doPerDatasource("merge", callback, local);
- },
- status: function(syncType, callback){
- var ds = createDatasource(syncType);
- var se = this._createSyncEngine(ds);
- se.status(callback);
- },
- extstatus: function(syncType, callback){
- var ds = createDatasource(syncType);
- var se = this._createSyncEngine(ds);
- se.extstatus(callback);
- },
- getProfileNames: function(callback){
- var se = this._createSyncEngine(null);
- se.getProfileNames(callback);
- },
- _getCorrelatorInfo: function(url, corruri, callback, flags){
- const https = "https://";
- flags = flags || {};
- var str;
- var self = this;
- var protocol = url.substr(0,https.length).toLowerCase();
- var funcFinished = function(status, response) {
- self._request = null;
- callback(status, response);
- };
-
- // we contact correlator via https if the url we are interested
- // in is https
- if (Xmarks.gSettings.securityLevel == 1 || protocol == https ){
- str = https;
- } else {
- str = "http://";
- }
-
- str += Xmarks.gSettings.apiHost + corruri;
- this._request = new Request(
- "POST",
- str,
- {
- urls: [url],
- mid: Xmarks.gSettings.machineId,
- apihost: Xmarks.gSettings.apiHost,
- drifthost: Xmarks.gSettings.driftHost,
- statichost: Xmarks.gSettings.staticHost,
- cid: "xmfx"
- },
- {
- isAuthRequest: false,
- headers: null,
- ignoreBody: false,
- noJSON: flags.noJSON,
- noAuthDialog: true
- }
- );
- this._request.Start(funcFinished);
- },
- getSimilarSites: function(url, callback){
- return this._getCorrelatorInfo(
- url,
- "/internal/bib",
- callback,
- {
- noJSON: true
- }
- );
- },
- getTurboTags: function(url, callback){
- return this._getCorrelatorInfo(url, "/internal/topics_review/read",
- callback);
- },
-
- updateReview: function(url, url_id, rating, review, callback) {
- var useSSL = (Xmarks.gSettings.securityLevel == 1 ||
- url.indexOf("https://") == 0);
- this._request = new Request("POST",
- { protocol: useSSL ? "https" : "http",
- host: Xmarks.gSettings.apiHost,
- path: "/internal/review/write" },
- { url_id: url_id, rating: rating, review: review });
- this._request.Start(callback);
- },
-
- purgepasswords: function(callback){
- var ds = createDatasource("passwords");
- var se = this._createSyncEngine(ds);
- se.purgepasswords(callback);
- },
- restore: function(rev,callback){
- var ds = createDatasource("bookmarks");
- var se = this._createSyncEngine(ds);
- try {
- se.restore(rev,callback);
- } catch(e){
- Xmarks.LogWrite("Restore Failed (" + e.message + ")");
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- }
- },
- getrevision: function(rev,callback){
- var ds = createDatasource("bookmarks");
- var se = this._createSyncEngine(ds);
- try {
- se.getrevision(rev,callback);
- } catch(e){
- Xmarks.LogWrite("GetRevision Failed (" + e.message + ")");
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- }
- },
- getrevisions: function(callback){
- var ds = createDatasource("bookmarks");
- var se = this._createSyncEngine(ds);
- try {
- se.getrevisions(callback);
- } catch(e){
- Xmarks.LogWrite("GetRevision Failed (" + e.message + ")");
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- }
- },
- verifypin: function(pin, callback){
- var ds = createDatasource("passwords");
- var se = this._createSyncEngine(ds);
- try {
- se.verifypin(pin, callback);
- } catch(e){
- Xmarks.LogWrite("Verify Pin Failed (" + e.message + ")");
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- }
- },
- runUnitTest: function(){
- gFoxmarksUT.run();
- },
- countItems: function(synctype, itemtype, callback){
- var ds = createDatasource(synctype);
- var se = this._createSyncEngine(ds);
- se.countItems(itemtype, callback);
- }
- };
-
-
- function SyncEngine(datasource) {
- this._datasource = datasource;
- }
-
- SyncEngine.prototype = {
- request: null,
- _iscancelled: false,
-
- get _baseline() {
- return this._mgr._baselineCache[
- this._datasource.syncType
- ];
- },
- set _baseline(val) {
- this._mgr._baselineCache[
- this._datasource.syncType
- ] = val;
- },
-
- cancel: function() {
- if (this.request) {
- this.request.Cancel();
- }
- this._iscancelled = true;
- },
- isCancelled: function(){
- return this._iscancelled;
- },
-
- _responseOK: function(response, callback) {
- if(this.isCancelled()){
- callback(2);
- return false;
- }
- else if (typeof response == 'number') {
- if (!response) {
- return true;
- } else {
- callback(response);
- }
- } else if (typeof response == 'object') {
- if (!response.status) {
- return true;
- } else {
- if (response.status == 403) {
- Xmarks.LogWrite("Got a 403");
- Handle403(response);
- } else if (response.status == 503) {
- try {
- gServerBackoff[this._datasource.syncType] = response.backoff_delay || 0;
- if (gServerBackoff[this._datasource.syncType]) {
- Xmarks.LogWrite("Server wants us to wait " +
- gServerBackoff[this._datasource.syncType] + " seconds");
- }
- } catch(e) {}
- }
- callback(response.status);
- return false;
- }
- } else {
- throw Error("unexpected response type: " + response);
- }
- },
- countItems: function(itemtype, callback){
- var self = this;
- var ns = new Nodeset(self._datasource);
- ns.FetchFromNative(function(status){
- if (self._responseOK(status, callback)) {
- var ctr = 0;
- ns.OnTree(
- function(nid){
- if(ns.Node(nid).ntype == itemtype)
- ctr++;
- },
- function(){
- callback(status, ctr);
- }
- );
- }
- });
- },
- sync: function(prevState, callback) {
- // Local Vars
- var lns = null, sns = null;
- var lcs = null, scs = null;
- var sco = null;
- var lastModified = 0;
- var self = this;
- var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
- getService(Ci.nsIFoxmarksService);
- self.startTime = Xmarks.LogTimer("Timer Sync Start");
- var funcCheckStatus = function(status, response) {
- if (self._responseOK(status, callback)) {
- if (response.isreset == true) {
- self.upload(callback);
- } else {
- self.merge(true, callback);
- }
- }
- };
-
- // Local functions
- var funcGetServerChanges = function(status) {
- if (self._responseOK(status, callback)) {
- Xmarks.LogTimer("Timer Sync: Fetch Baseline", self.startTime);
- // Get changes.
- self._getServerChanges(funcGotServerChanges);
- }
- };
- var funcGotServerChanges = function(status, serverContextObject) {
- if (self._responseOK(status, callback)) {
- Xmarks.LogTimer("Timer Sync: Got Server Changes", self.startTime);
- sco = serverContextObject;
- if (!sco.continuous) {
- // Someone has done an upload. Allow the user the option
- // of performing a merge or a download.
-
- switch (self._datasource.DiscontinuityPrompt()) {
- case 0: // merge
- return self.merge(false, callback);
-
- case 1: // download
- return self.download(callback);
-
- case 2: // cancel
- callback(2);
- return;
- }
- }
- if (!sco.mscs.length && prevState == 'ready' &&
- self._haveFetched) {
- Xmarks.LogWrite("Nothing to see here; move along.");
- callback(0);
- return;
- }
-
- //Xmarks.SetProgressMessage("progress.syncing");
- scs = sco.mscs;
- sns = sco.sns;
-
- // Calculate minimal local change set.
- lastModified = fms.getLastModified(self._datasource.synctype);
- lns = new Nodeset(self._datasource);
- lns.FetchFromNative(funcGotLocalNodeset);
- self._haveFetched = true;
- }
- }
- var funcGotLocalNodeset = function(status) {
- if (self._responseOK(status, callback)) {
- Xmarks.LogTimer("Timer Sync: Fetched Local", self.startTime);
- var base = new Nodeset(self._datasource,self._baseline);
- base.Compare(lns, funcGetLocalCommandset);
- }
- }
- var funcGetLocalCommandset = function(status, lcs) {
- if (self._responseOK(status, callback)) {
- Xmarks.LogTimer("Timer Sync: Command Set", self.startTime);
- // Check to see whether there's been a clobber
- if (lns.length < 3 * self._baseline.length / 4) {
- Xmarks.LogWrite("Yikes! Length was " + self._baseline.length +
- " but is now " + lns.length);
- self.manual = true;
- if (!self._datasource.ClobberDialog(lns.length, self._baseline.length)) {
- // User canceled. Back off for 24 hours.
- gBackoffUntil = Date.now() + 24 * 60 * 60 * 1000;
- callback(2);
- return;
- }
- }
-
- Xmarks.LogWrite("lcs = " + lcs.length + " scs = " + scs.length);
-
- try {
- Synchronize(self._baseline, lcs, scs, lns, sns,
- funcSyncComplete);
- } catch (e) {
- Xmarks.LogWrite("Synchronization failed. Error is " +
- e.toSource());
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- }
- }
- };
- var funcSyncComplete = function(finalLcs,
- finalScs,
- conflicts,
- showedUI) {
- Xmarks.LogTimer("Timer Sync: Sync Set", self.startTime);
- //Xmarks.SetProgressMessage("progress.writing");
-
- if (showedUI) {
- self.manual = true;
- }
-
- if (lastModified != fms.getLastModified(self._datasource.synctype)) {
- Xmarks.LogWrite("Local datastore changed during sync");
- Xmarks.LogWrite("lastModified " + lastModified + " != " + fms.getLastModified(self._datasource.synctype));
- callback(409);
- return;
- }
-
- // Scoping: assign back to our enclosing function's locals
- lcs = finalLcs;
- scs = finalScs;
-
- // Apply the server's changes to the local set.
- try {
- lns = new Nodeset(self._datasource, lns);
- scs.execute(lns);
- Xmarks.LogTimer("Timer Sync: Applied Changes", self.startTime);
- } catch (e) {
- Xmarks.LogWrite("execute failed: " + e.toSource());
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- return;
- }
-
- // Write local changes (if any) to the server.
- if (lcs.set.length > 0) {
- self._writeServerChanges(lcs, lns, sco, conflicts,
- funcWroteServerChanges);
- } else {
- funcWroteServerChanges();
- }
- };
- var funcWroteServerChanges = function(obj) {
- if (obj) { // We had something to write
- if (self._responseOK(obj, callback)) {
- } else {
- Xmarks.LogWrite("putchanges failed; response is " +
- obj.toJSONString());
- return;
- }
- }
-
- Xmarks.LogTimer("Timer Sync: Sent Server Changes", self.startTime);
- // Flush the local nodeset back to the native datastore if it changed.
- if (scs.set.length > 0) {
- //Xmarks.SetProgressMessage("progress.loading");
- lns.FlushToNative(funcWroteLocalChanges);
- } else {
- funcWroteLocalChanges(0);
- }
- };
- var funcWroteLocalChanges = function(response) {
- // If we got changes from the server or wrote changes to
- // the server, we'll have a new revision number. If neither
- // of these happened, then the sync was a big no-op.
- if (self._responseOK(response, callback)) {
- Xmarks.LogTimer("Timer Sync: Wrote to Native", self.startTime);
- if (lcs.set.length > 0 || scs.set.length > 0) {
- self._completeTransaction(lns, sco, callback);
- } else {
- // We didn't do anything, but note that we successfully
- // Synced nonetheless.
- callback(0); // Done!
- }
- }
- };
-
- // function start
-
- // If we've never synced, do an upload or merge.
- if (!Xmarks.gSettings.getHaveSynced(self._datasource.syncType)) {
- self.status(funcCheckStatus);
- }
- else {
- if(Xmarks.gSettings.mustUpload(self._datasource.syncType)){
- Xmarks.LogWrite("Forced Upload: Pin Reset");
- self.upload(function(response){
- if(self._responseOK(response, callback)){
- Xmarks.gSettings.setMustUpload(self._datasource.syncType, false);
- callback(response);
- }
- });
- return;
-
- }
- else if(Xmarks.gSettings.mustMerge(self._datasource.syncType)){
- Xmarks.LogWrite("Forced Merge for Passwords");
- self.merge(true, function(response){
- if(self._responseOK(response, callback)){
- Xmarks.gSettings.setMustMerge(self._datasource.syncType, false);
- callback(response);
- }
- });
- return;
-
- }
- // Normal sync: make sure we've got a baseline to work with.
- //Xmarks.SetProgressMessage("progress.downloading");
- self._fetchBaseline(funcGetServerChanges);
- return;
- }
- }
- };
-
-
- function Syncd2SyncEngine(mgr, datasource) {
- this._datasource = datasource;
- this._mgr = mgr;
- }
- Syncd2SyncEngine.prototype = new SyncEngine;
-
- function OwnSyncEngine(mgr, datasource) {
- this._datasource = datasource;
- this._mgr = mgr;
- }
- OwnSyncEngine.prototype = new SyncEngine;
-
- Syncd2SyncEngine.prototype._args = function(dict, ignoreUpload) {
- if (this.manual) {
- dict["manual"] = true;
- }
- if (gFailureCount) {
- dict["retry"] = gFailureCount;
- }
- if (Xmarks.gSettings.machineId) {
- if (!dict["log"]) {
- dict["log"] = {};
- }
- dict["log"]["mid"] = Xmarks.gSettings.machineId;
- dict["log"]["serp"] = Xmarks.gSettings.serpEnabled ? Xmarks.gSettings.serpMaxItems : 0;
- dict["log"]["ssEnabled"] = Xmarks.gSettings.simsiteEnabled;
-
- var st = [];
- for(var x = 0; x < 10; x++){
- st.push(Xmarks.gSettings.getST(false,x));
- }
-
- if(st.toSource() != "[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}]"){
- dict["log"]["st"] = st;
- }
- st = [];
- for(var x = 0; x < 10; x++){
- st.push(Xmarks.gSettings.getST(true,x));
- Xmarks.gSettings.clearST(x);
- }
-
- if(st.toSource() != "[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}]"){
- dict["log"]["ust"] = st;
- }
- if(Xmarks.gSettings.trSERP){
- dict["log"]["trs"] = Xmarks.gSettings.trSERP;
- Xmarks.gSettings.trSERP = "";
- }
- if(Xmarks.gSettings.numTurboTags){
- dict["log"]["ttags"] = Xmarks.gSettings.numTurboTags;
- Xmarks.gSettings.numTurboTags = 0;;
- }
- }
- if (Xmarks.gSettings.viewId) {
- if(!ignoreUpload){
- dict.view = Xmarks.gSettings.viewId;
- }
- }
-
-
- return dict;
- }
-
- Syncd2SyncEngine.prototype.upload = function(callback) {
- var self = this;
- var ns = new Nodeset(this._datasource);
-
- // if we are doing a force upload, then that trumps forcedMerge
- if(Xmarks.gSettings.mustUpload(self._datasource.syncType)){
- Xmarks.gSettings.setMustMerge(self._datasource.syncType, false);
- }
- // even though the user says upload, we don't want
- // to do that for passwords during initial sync
- if(Xmarks.gSettings.mustMerge(self._datasource.syncType)){
- Xmarks.LogWrite("Forced Merge for Passwords");
- self.merge(true, function(response){
- if(self._responseOK(response, callback)){
- Xmarks.gSettings.setMustMerge(self._datasource.syncType, false);
- callback(response);
- }
- });
- return;
- }
-
- // Hack: we don't seem to be able to handle
- // authentication during an upload request.
- // So to avoid trouble, we do a throw-away
- // status request first. If auth is required,
- // it will be handled during the status request,
- // after which we will get on to our real work.
-
- var funcForceAuth = function(status) {
- if (self._responseOK(status, callback)) {
- //Xmarks.SetProgressMessage("progress.writing");
- ns.FetchFromNative(funcFetched);
- }
- };
- var funcFetched = function(e) {
- if (e) {
- callback(e);
- return;
- }
- ns.ProvideCommandset(funcContinue);
- };
- var funcContinue = function(status, cs) {
- if (self._responseOK(status, callback)) {
- self.request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/upload",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- },
- self._args({ "commands" : cs },
- Xmarks.gSettings.mustUpload(self._datasource.syncType)
- )
- );
- self.request.Start(funcDone);
- }
- };
- var funcDone = function(response) {
- if (self._responseOK(response, callback)) {
- if (!response.toprev) {
- Xmarks.LogWrite("Error: Invalid response to upload");
- callback(500);
- } else {
- Xmarks.gSettings.setMustUpload(self._datasource.syncType, false);
- self._completeTransaction(ns, { toprev: response.toprev },
- callback);
- }
- }
- };
-
- if (Xmarks.gSettings.viewId && !Xmarks.gSettings.mustUpload(self._datasource.syncType)) {
- this._uploadWithProfile(callback);
- return;
- }
- self.status(funcForceAuth);
- }
-
- Syncd2SyncEngine.prototype.purgepasswords = function(callback) {
- var self = this;
- var ns = new Nodeset(this._datasource);
-
- // Hack: we don't seem to be able to handle
- // authentication during an upload request.
- // So to avoid trouble, we do a throw-away
- // status request first. If auth is required,
- // it will be handled during the status request,
- // after which we will get on to our real work.
-
- var funcForceAuth = function(status) {
- if (self._responseOK(status, callback)) {
- self.request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/purge",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- } , self._args({ mode: "data"}));
- self.request.Start(function(statuspurge){
- if (self._responseOK(statuspurge, callback)) {
- Xmarks.gSettings.SetSyncRevision(
- self._datasource.syncType, 0);
- callback(0);
- }
- });
- }
- };
- self.status(funcForceAuth);
- }
- Syncd2SyncEngine.prototype._uploadWithProfile = function(callback) {
- var self = this;
- var revision;
- var ns;
- var lns;
-
- var funcDone = function(response) {
- if (self._responseOK(response, callback)) {
- if (!response.toprev || !response.commands) {
- Xmarks.LogWrite("Error: Invalid response to download");
- callback(500);
- return;
- }
- revision = response.toprev;
- ns = new Nodeset(self._datasource);
- var cs = new Commandset(response.commands);
- try {
- cs.execute(ns);
- } catch (e) {
- Xmarks.LogWrite("execute failed: " + e.toSource());
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- return;
- }
-
- // Retrieve local set.
- lns = new Nodeset(self._datasource);
- lns.FetchFromNative(funcGotLocal);
- }
- };
- var funcGotLocal = function(response) {
- // Calculate difference: server -> local.
- if (self._responseOK(response, callback)) {
- ns.Compare(lns, funcCompared);
- }
- };
- var funcCompared = function(status, cs) {
- if (self._responseOK(status, callback)) {
- if (cs.length) {
- //Xmarks.SetProgressMessage("progress.uploading");
- self.request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/putchanges",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- },
- self._args({ "baserev": revision, "commands" : cs }));
- self.request.Start(funcFinished);
- } else {
- funcFinished({ status: 0, toprev: revision});
- }
- }
- };
- var funcFinished = function(response) {
- if (self._responseOK(response, callback)) {
- if (!response.toprev) {
- Xmarks.LogWrite("Error: Invalid response to putchanges");
- callback(500);
- } else {
- self._completeTransaction(ns, { toprev: response.toprev },
- callback);
- }
- }
- };
-
-
- // Download current server state.
- Xmarks.SetProgressMessage("progress.downloading");
- self.request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/download",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- }, self._args({}));
- self.request.Start(funcDone);
- }
-
- Syncd2SyncEngine.prototype.download = function(callback, rev) {
- var self = this;
- var ns;
- var revision;
-
- // resetPIN trumps download (only occurs in the case of
- // resetPIN in setup dialog)
- if(Xmarks.gSettings.mustUpload(self._datasource.syncType)){
- Xmarks.LogWrite("Forced Upload: Pin Reset");
- self.upload(function(response){
- if(self._responseOK(response, callback)){
- Xmarks.gSettings.setMustUpload(self._datasource.syncType, false);
- callback(response);
- }
- });
- return;
- }
- else if(Xmarks.gSettings.mustMerge(self._datasource.syncType)){
- Xmarks.LogWrite("Forced Merge for Passwords");
- self.merge(true, function(response){
- if(self._responseOK(response, callback)){
- Xmarks.gSettings.setMustMerge(self._datasource.syncType, false);
- callback(response);
- }
- });
- return;
- }
- var funcDone = function(response) {
- if (self._responseOK(response, callback)) {
- if (!response.toprev || !response.commands) {
- Xmarks.LogWrite("Error: Invalid response to download");
- callback(500);
- return;
- }
- revision = response.toprev;
- ns = new Nodeset(self._datasource);
- var cs = new Commandset(response.commands);
- try {
- cs.execute(ns);
- } catch (e) {
- Xmarks.LogWrite("execute failed: " + e.toSource());
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- return;
- }
- //Xmarks.SetProgressMessage("progress.loading");
- ns.FlushToNative(funcFinished);
- }
- };
- var funcFinished = function(response) {
- if (self._responseOK(response, callback)) {
- if(!rev){
- self._completeTransaction(ns, { toprev: revision }, callback);
- } else {
- callback(response);
- }
- }
- };
-
- //Xmarks.SetProgressMessage("progress.downloading");
- var params = {};
- if(rev){
- params.rev = rev;
- }
- self.request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/download",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- }, self._args(params));
- self.request.Start(funcDone);
- }
-
-
- Syncd2SyncEngine.prototype.verifypinbrokenroot = function(pin, callback) {
- var self = this;
- var ns;
- var revision;
-
- var funcDone = function(response) {
- if (self._responseOK(response, callback)) {
- for(var nid in response.nodes){
- if(!response.nodes.hasOwnProperty(nid)){
- continue;
- } else if(response.nodes[nid].data){
- var result = self._datasource.verifyPin(pin, response.nodes[nid]);
- callback(result ? 0 : 100);
- return;
- }
- }
- // must have been no nodes with data, so assume it's valide
- callback(0);
- }
- };
-
- //Xmarks.SetProgressMessage("progress.verifying");
- Xmarks.LogWrite("Verifying PIN Broken Root");
- self.request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/state",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- }, {"nodes":"ROOT", "depth":"children"});
- self.request.Start(funcDone);
- }
-
- Syncd2SyncEngine.prototype.restore = function(rev,callback) {
- var self = this;
-
- this.download(
- function(response){
- if (self._responseOK(response, callback)) {
- // self.upload(callback);
- self.sync('dirty',
- function(response){
- if (self._responseOK(response, callback)) {
- Xmarks.gSettings.SyncComplete(
- self._datasource.syncType
- );
- }
- callback(response);
- }
- );
- }
- },
- rev
- );
- }
-
- Syncd2SyncEngine.prototype.getrevision = function(rev,callback) {
- var self = this;
- var funcFetched = function(response) {
- if (self._responseOK(response, callback)) {
- callback(0, response);
- }
- }
-
- //Xmarks.SetProgressMessage("progress.gettingprofilenames");
- var request = new Request("POST",
- { path: "/sync/bookmarks/state",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType) },
- this._args({rev: rev}) );
- request.Start(funcFetched);
-
- }
- Syncd2SyncEngine.prototype.getrevisions = function(callback) {
- var self = this;
- var funcFetched = function(response) {
- if (self._responseOK(response, callback)) {
- callback(0, response);
- }
- }
-
- //Xmarks.SetProgressMessage("progress.gettingprofilenames");
- var request = new Request("POST",
- { path: "/sync/bookmarks/getrevisions",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType) },
- this._args({limit: Xmarks.gSettings.getRevisionLimit}) );
- request.Start(funcFetched);
-
- }
- Syncd2SyncEngine.prototype.verifypin = function(pin, callback) {
- var self = this;
- var ns;
- var revision;
-
- var funcDone = function(response) {
- if (self._responseOK(response, callback)) {
- Xmarks.LogWrite("Verifying PIN (Received Test Node)");
- if(!response.nodes.ROOT.data){
- Xmarks.LogWrite("WARNING: Bad Root Problem");
- self.verifypinbrokenroot(pin, callback);
- } else {
- var result = self._datasource.verifyPin(pin, response.nodes.ROOT);
- callback(result ? 0 : 100);
- }
- }
- };
-
- //Xmarks.SetProgressMessage("progress.verifying");
- Xmarks.LogWrite("Verifying PIN (Starting)");
- self.request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/state",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- }, {"nodes":"ROOT", "depth":"self"});
- self.request.Start(funcDone);
- }
- // Fetch changes from the server. Passes to callback an object containing:
- // * continous: true if the changes on the server are continuous.
- // * mscs: the minimal server commandset.
- // * other server context info (in this case, toprev) to passed into
- // _writeServerChanges().
-
-
- Syncd2SyncEngine.prototype._getServerChanges = function(callback) {
- // Get changes.
- var self = this;
- var toprev = 0;
- var sns = new Nodeset(self._datasource, self._baseline);
-
- var funcProcessResponse = function(response) {
- if (self._responseOK(response, callback)) {
- if (response.continuous == false) {
- callback(0, { continuous: false });
- } else {
- if (!response.toprev || !response.commands) {
- Xmarks.LogWrite("Error: Invalid response to getchanges");
- callback(500);
- return;
- }
- toprev = response.toprev;
- // Calculate mcs.
- if (response.commands.length) {
- scs = new Commandset(response.commands);
- try {
- scs.execute(sns);
- } catch (e) {
- Xmarks.LogWrite("execute failed: " + e.toSource());
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- return;
- }
- var base = new Nodeset(self._datasource,self._baseline);
- base.Compare(sns, funcCalculatedMcs);
- } else {
- // Not modified
- callback(0, { mscs: new Commandset(), toprev: toprev,
- sns: sns, continuous: true});
- }
- }
- }
- };
- var funcCalculatedMcs = function(status, cs) {
- if (self._responseOK(status, callback)) {
- Xmarks.LogWrite(">>> Finished mcs: " + cs.toSource());
- callback(0, { mscs: cs, toprev: toprev, continuous: true,
- sns: sns });
- }
- };
-
- self.request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/getchanges",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- },
- self._args({ "baserev": self._baseline.currentRevision}) );
- self.request.Start(funcProcessResponse);
- }
-
- OwnSyncEngine.prototype.testDupURL = function(){
- // force check to see if user has two different urls for password
- // and bookmark
- if(Xmarks.gSettings.isSyncEnabled("bookmarks") &&
- Xmarks.gSettings.isSyncEnabled("passwords")){
- if(Xmarks.gSettings.getUrlWithUsernameAndPassword("passwords") ==
- Xmarks.gSettings.getUrlWithUsernameAndPassword("bookmarks")){
- return true;
- }
- }
- return false;
- }
- OwnSyncEngine.prototype._getServerChanges = function(callback) {
- // Download the file, but only if the etag doesn't match
- var self = this;
- var headers = {};
- var token;
- var etag;
- var sns;
-
- var funcProcessFile = function(response) {
- if (response.status == 304) { // Not modified.
- callback(0, { continuous: true, mscs: new Commandset(),
- token: Xmarks.gSettings.getToken(self._datasource.syncType), etag: response.etag });
- return;
- }
- if (self._responseOK(response, callback)) {
- if (response.token != Xmarks.gSettings.getToken(self._datasource.syncType)) {
- callback(0, { continuous: false, etag: response.etag } );
- return;
- }
-
- token = response.token;
- etag = response.etag;
- var cs = new Commandset(response.commands);
- sns = new Nodeset(self._datasource);
- try {
- sns.Execute(cs);
- } catch (e) {
- Xmarks.LogWrite("execute failed: " + e.toSource());
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- return;
- }
-
- var base = new Nodeset(self._datasource,self._baseline);
- base.Compare(sns, funcCompared);
- }
- };
- var funcCompared = function(status, cs) {
- if (self._responseOK(status)) {
- callback(0, { continuous: true, mscs: cs, token: token,
- sns: sns, etag: etag });
- }
- };
-
- var serveretag = Xmarks.gSettings.getEtag(this._datasource.syncType);
- if (serveretag.length) {
- headers["If-None-Match"] = serveretag;
- }
- self.request = new Request("GET",
- Xmarks.gSettings.getUrlWithUsernameAndPassword(
- self._datasource.syncType
- ),
- null,
- {
- isAuthRequest: false,
- headers: headers
- }
- );
- self.request.Start(funcProcessFile);
- }
-
- Syncd2SyncEngine.prototype._writeServerChanges = function(lcs, lns, sco, conflicts,
- callback) {
-
- var self = this;
- var funcWrote = function(response) {
- if (self._responseOK(response, callback)) {
- sco.toprev = response.toprev;
- if (!sco.toprev) {
- Xmarks.LogWrite("Error: Invalid response to putchanges");
- callback(500);
- } else {
- callback(0);
- }
- }
- };
-
- self.request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/putchanges",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- },
- self._args({ baserev : sco.toprev, commands : lcs, log : conflicts } ));
- self.request.Start(funcWrote);
- }
-
- OwnSyncEngine.prototype._writeServerChanges = function(lcs, lns, sco, conflicts,
- callback) {
- var self = this;
-
- var funcGotCommandset = function(status, cs) {
- var header = {};
- if (!Xmarks.gSettings.disableIfMatchOnPut && sco.etag && sco.etag.length) {
- header = { "Etag" : sco.etag };
- }
- if (self._responseOK(status, callback)) {
- self.request = new Request("PUT",
- Xmarks.gSettings.getUrlWithUsernameAndPassword(self._datasource.syncType),
- { token: sco.token, commands: cs },
- {
- isAuthRequest: false,
- headers: header,
- ignoreBody: true
- }
- );
- self.request.Start(funcWritten);
- }
- };
- var funcWritten = function(response) {
- if (self._responseOK(response, callback)) {
- sco.etag = response.etag;
- callback(0);
- }
- };
-
- lns.ProvideCommandset(funcGotCommandset);
- }
-
- Syncd2SyncEngine.prototype.status = function(callback) {
- var self = this;
-
- var funcCheckStatus = function(response) {
- if (self._responseOK(response, callback)) {
- if (!response.toprev) {
- Xmarks.LogWrite("Error: Invalid response to status");
- callback(500);
- return;
- }
- callback(0, response);
- }
- };
-
- Xmarks.LogWrite("Entered Status...");
- //Xmarks.SetProgressMessage("progress.verifying");
-
- self.request = new Request("POST",
- { path: "/sync/" + self._datasource.syncType + "/status",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- }, {});
- self.request.Start(funcCheckStatus);
- }
- Syncd2SyncEngine.prototype.extstatus = function(callback) {
- var self = this;
- this.status(function(normal_status,response){
- // if we get an error, do callback right away
- if(normal_status){
- callback(normal_status, response);
-
- // if we are reset, no need to check if we are purged
- } else if(response.isreset){
- response.ispurged = false;
- callback(normal_status, response);
- // call for the root to see if we get a 444
- } else {
- self.request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/state",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- }, {"nodes":"ROOT", "depth":"self"});
- self.request.Start(function(stateresponse){
- if (self._responseOK(stateresponse, function(errnum){
- if(errnum == 444){
- response.ispurged = true;
- callback(0, response);
- } else {
- callback(errnum, response);
- }
- })) {
- response.ispurged = false;
- callback(0, response);
- }
- });
- }
- });
-
- }
- OwnSyncEngine.prototype.status = function(callback) {
- var self = this;
-
- var funcHandleResponse = function(response) {
- if (response.status == 404) {
- callback(0, { status: 0, isreset: true, ispurged: false });
- } else if (self._responseOK(response, callback)) {
- callback(0, { status: 0, isreset: false, ispurged: false });
- }
- };
-
- Xmarks.LogWrite("Entered status...");
- if(this.testDupURL()){
- callback(1011);
- return;
- }
- //Xmarks.SetProgressMessage("progress.verifying");
- self.request = new Request("GET",
- Xmarks.gSettings.getUrlWithUsernameAndPassword(self._datasource.syncType));
- self.request.Start(funcHandleResponse);
- }
- OwnSyncEngine.prototype.extstatus = OwnSyncEngine.prototype.status;
-
-
- Syncd2SyncEngine.prototype._getServerState = function(callback) {
- var self = this;
- self.request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/download",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- }, self._args({}) );
- self.request.Start(callback);
- }
-
- OwnSyncEngine.prototype._getServerState = function(callback) {
- var self = this;
- self.request = new Request("GET",
- Xmarks.gSettings.getUrlWithUsernameAndPassword(self._datasource.syncType));
- self.request.Start(callback);
- }
-
- SyncEngine.prototype.merge = function(local, callback) {
- // Perform a merge (an "additive sync").
- // local is a boolean which determines what merge uses
- // as the starting set: true for local, false for server.
-
- Xmarks.LogWrite("Entered Merge...");
-
- var self = this;
- var serverNS = new Nodeset(self._datasource);
- var localNS = new Nodeset(self._datasource);
- var mergedNS = null;
- var revision;
- var sco;
-
- // resetPIN trumps merge
- if(Xmarks.gSettings.mustUpload(self._datasource.syncType)){
- Xmarks.LogWrite("Forced Upload: Pin Reset");
- self.upload(function(response){
- if(self._responseOK(response, callback)){
- Xmarks.gSettings.setMustUpload(self._datasource.syncType, false);
- callback(response);
- }
- });
- return;
- }
-
- var funcDone = function(response) {
- if (self._responseOK(response, callback)) {
- sco = response;
- var cs = new Commandset(response.commands);
- try {
- cs.execute(serverNS);
- } catch (e) {
- if(typeof e == "number"){
- callback(e);
- } else {
- Xmarks.LogWrite("execute failed: " + e.toSource());
- callback(4);
- }
- return;
- }
- localNS.FetchFromNative(funcFetched);
- }
- };
- var funcFetched = function( e ) {
-
- if (e) {
- callback(e);
- return;
- }
- //Xmarks.SetProgressMessage("progress.merging");
- if (local) {
- localNS.Merge(serverNS);
- mergedNS = localNS;
- } else {
- mergedNS = new Nodeset(self._datasource, serverNS);
- mergedNS.Merge(localNS);
- }
-
- // calculate server's MCS
- Xmarks.LogWrite("Finished merge; calculating mcs");
- serverNS.Compare(mergedNS, funcWriteChanges);
- };
- var funcWriteChanges = function(status, cs) {
- if (self._responseOK(status, callback)) {
- // Write changes to the server.
- //Xmarks.SetProgressMessage("progress.writing");
- if (cs.set.length > 0) {
- self._writeServerChanges(cs, mergedNS, sco, null,
- funcWroteServerChanges);
- } else {
- funcWroteServerChanges(0);
- }
- }
- };
- var funcWroteServerChanges = function(response) {
- // Write 'em back to native store, too
- if (self._responseOK(response, callback)) {
- //Xmarks.SetProgressMessage("progress.loading");
- mergedNS.FlushToNative(funcFlushed);
- }
- };
- var funcFlushed = function(response) {
- if (self._responseOK(response, callback)) {
- Xmarks.gSettings.setMustMerge(self._datasource.syncType, false);
- self._completeTransaction(mergedNS, sco, callback);
- }
- };
-
- //Xmarks.SetProgressMessage("progress.downloading");
- self._getServerState(funcDone);
- }
-
- Syncd2SyncEngine.prototype._fetchBaseline = function(callback) {
- // Fetch the baseline if necessary
- var self = this;
-
- var funcLoadedFromServer = function(response) {
- if (self._responseOK(response, callback)) {
- var cs = new Commandset(response.commands);
- try {
- cs.execute(self._baseline);
- } catch (e) {
- Xmarks.LogWrite("execute failed: " + e.toSource());
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- return;
- }
- self._baseline.currentRevision = response.rev;
- self._baseline.SaveToFile(funcLoaded);
- return;
- } else {
- Xmarks.LogWrite("Failed to load baseline from server.");
- }
- };
- var funcLoaded = function() {
- // Loaded from file or server
- // var nat = new NativeDatasource();
- self._baseline.BaselineLoaded(self._baseline, funcGotIt);
- return;
- };
- var funcGotIt = function(status) {
- if (self._responseOK(status, callback)) {
- self._baseline.hash = Xmarks.gSettings.hash;
- callback(0);
- }
- };
-
- if (self._baseline && self._baseline.hash == Xmarks.gSettings.hash) {
- Xmarks.LogWrite("Using Baseline Cache.");
- funcGotIt(0);
- return;
- }
-
- self._baseline = new Nodeset(self._datasource);
- try {
- self._baseline.LoadFromFile();
- } catch (e) {
- // We failed to load our baseline locally -- try getting
- // it from the server.
- Xmarks.LogWrite("Failed to load baseline from file: " + e.name);
- var request = new Request("POST",
- {
- path: "/sync/" + self._datasource.syncType + "/download",
- host: Xmarks.gSettings.getServerHost(self._datasource.syncType)
- },
- self._args({ rev: Xmarks.gSettings.GetSyncRevision(self._datasource.syncType), depth: "all",
- log: { "error": e.name }}));
- request.Start(funcLoadedFromServer);
- return;
- }
-
- funcLoaded();
- }
-
- OwnSyncEngine.prototype._fetchBaseline = function(callback) {
- // Fetch the baseline if necessary
- var self = this;
-
- var funcLoaded = function() {
- // Loaded from file
- // var nat = new NativeDatasource();
- self._baseline.BaselineLoaded(self._baseline, funcGotIt);
- };
- var funcGotIt = function(status) {
- if (self._responseOK(status, callback)) {
- self._baseline.hash = Xmarks.gSettings.hash;
- callback(0);
- }
- };
-
- if (self._baseline && self._baseline.hash == Xmarks.gSettings.hash) {
- funcGotIt(0);
- return;
- }
-
- self._baseline = new Nodeset(self._datasource);
- try {
- self._baseline.LoadFromFile();
- } catch (e) {
- // We failed to load our baseline locally -- we're hosed.
- Xmarks.LogWrite("Failed to load baseline.");
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- return;
- }
-
- funcLoaded();
- }
-
- Syncd2SyncEngine.prototype._completeTransaction = function(ns, sco, callback) {
- var self = this;
-
- var funcFinishUp = function(status) {
- if (self._responseOK(status, callback)) {
- self._baseline = ns;
- self._baseline.hash = Xmarks.gSettings.hash;
- self._baseline.currentRevision = sco.toprev;
- self._baseline.SaveToFile(funcFinishedWrite);
- }
- };
- var funcFinishedWrite = function(status) {
- if (self._responseOK(status, callback)) {
- // Xmarks.gSettings.currentRevision = sco.toprev;
- Xmarks.gSettings.SetSyncRevision(self._datasource.syncType, sco.toprev);
- callback(0);
- }
- };
-
- ns.Declone(funcFinishUp);
- }
-
- Syncd2SyncEngine.prototype.getProfileNames = function(callback) {
- var self = this;
- var funcFetched = function(response) {
- if (self._responseOK(response, callback)) {
- callback(0, response);
- }
- }
-
- //Xmarks.SetProgressMessage("progress.gettingprofilenames");
- var request = new Request("POST",
- { path: "/user/profiles/getnames",
- host: Xmarks.gSettings.acctMgrHost },
- this._args({}) );
- request.Start(funcFetched);
-
- }
-
- OwnSyncEngine.prototype.upload = function(callback) {
- var self = this;
- var ns = new Nodeset(self._datasource);
- var token = Date.now().toString(16);
-
- // if we are doing a force upload, then that trumps forcedMerge
- if(Xmarks.gSettings.mustUpload(self._datasource.syncType)){
- Xmarks.gSettings.setMustMerge(self._datasource.syncType, false);
- }
- // even though the user says upload, we don't want
- // to do that for passwords during initial sync
- if(Xmarks.gSettings.mustMerge(self._datasource.syncType)){
- Xmarks.LogWrite("Forced Merge for Passwords");
- self.merge(true, function(response){
- if(self._responseOK(response, callback)){
- Xmarks.gSettings.setMustMerge(self._datasource.syncType, false);
- callback(response);
- }
- });
- return;
- }
-
-
- var funcFetched = function(status) {
- if (self._responseOK(status, callback)) {
- ns.ProvideCommandset(funcContinue);
- }
- };
- var funcContinue = function(status, cs) {
- if (self._responseOK(status, callback)) {
- self.request = new Request("PUT",
- Xmarks.gSettings.getUrlWithUsernameAndPassword(self._datasource.syncType),
- { commands: cs, token: token },
- { ignoreBody: true }
- );
- self.request.Start(funcDone);
- }
- };
- var funcDone = function(response) {
- if (self._responseOK(response, callback)) {
- Xmarks.gSettings.setMustUpload(self._datasource.syncType, false);
- self._completeTransaction(ns,
- { etag: response.etag, token: token }, callback);
- }
- };
-
- //Xmarks.SetProgressMessage("progress.writing");
- ns.FetchFromNative(funcFetched);
- }
-
- OwnSyncEngine.prototype.verifypin = function(pin, callback) {
- var self = this;
- var ns;
-
- var funcDone = function(response) {
- var funcFinished = function(resp) {
- if (self._responseOK(resp, callback)) {
- self._completeTransaction(ns,
- { etag: response.etag, token: response.token }, callback);
- }
- };
- if (self._responseOK(response, callback)) {
- ns = new Nodeset(self._datasource);
- var cs = new Commandset(response.commands);
- try {
- cs.execute(ns);
- } catch (e) {
- Xmarks.LogWrite("execute failed: " + e.toSource());
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- return;
- }
-
- var result = self._datasource.verifyPin(pin, ns.Node(NODE_ROOT));
- callback(result ? 0 : 100);
- }
- };
- //Xmarks.SetProgressMessage("progress.verifying");
- Xmarks.LogWrite("Verifying PIN (Own Server)");
- self.request = new Request("GET", Xmarks.gSettings.getUrlWithUsernameAndPassword(self._datasource.syncType));
- self.request.Start(funcDone);
- }
-
- OwnSyncEngine.prototype.download = function(callback) {
- var self = this;
- var ns;
-
- // resetPIN trumps download (only occurs in the case of
- // resetPIN in setup dialog)
- if(Xmarks.gSettings.mustUpload(self._datasource.syncType)){
- Xmarks.LogWrite("Forced Upload: Pin Reset");
- self.upload(function(response){
- if(self._responseOK(response, callback)){
- Xmarks.gSettings.setMustUpload(self._datasource.syncType, false);
- callback(response);
- }
- });
- return;
- }
- else if(Xmarks.gSettings.mustMerge(self._datasource.syncType)){
- Xmarks.LogWrite("Forced Merge for Passwords");
- self.merge(true, function(response){
- if(self._responseOK(response, callback)){
- Xmarks.gSettings.setMustMerge(self._datasource.syncType, false);
- callback(response);
- }
- });
- return;
- }
-
- var funcDone = function(response) {
- var funcFinished = function(resp) {
- if (self._responseOK(resp, callback)) {
- self._completeTransaction(ns,
- { etag: response.etag, token: response.token }, callback);
- }
- };
- if (self._responseOK(response, callback)) {
- ns = new Nodeset(self._datasource);
- var cs = new Commandset(response.commands);
- try {
- cs.execute(ns);
- } catch (e) {
- Xmarks.LogWrite("execute failed: " + e.toSource());
- if(typeof e == "number"){
- callback(e);
- } else {
- callback(4);
- }
- return;
- }
- //Xmarks.SetProgressMessage("progress.loading");
- ns.FlushToNative(funcFinished);
- }
- };
-
- //Xmarks.SetProgressMessage("progress.downloading");
- self.request = new Request("GET", Xmarks.gSettings.getUrlWithUsernameAndPassword(self._datasource.syncType));
- self.request.Start(funcDone);
- }
-
- OwnSyncEngine.prototype._completeTransaction =
- function(ns, sco, callback) {
- var self = this;
-
- var funcFinishUp = function(status) {
- if (self._responseOK(status, callback)) {
- self._baseline = ns;
- self._baseline.hash = Xmarks.gSettings.hash;
- self._baseline.SaveToFile(funcFinishedWrite);
- }
- };
- var funcFinishedWrite = function(status) {
- if (self._responseOK(status, callback)) {
- Xmarks.gSettings.setToken(self._datasource.syncType, sco.token);
- if (sco.etag) Xmarks.gSettings.setEtag(self._datasource.syncType, sco.etag);
- Xmarks.gSettings.SyncComplete(self._datasource.syncType);
- callback(0);
- }
- };
- ns.Declone(funcFinishUp);
- }
-
-
-